package org.zjx.task;

import lombok.Data;
import org.zjx.task.core.ITask;
import org.zjx.task.core.TaskScheduler;
import org.zjx.task.exception.TaskExecutionException;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Data
public abstract class AbstractTask implements ITask {
    protected final String taskId;
    protected final Map<String, Object> params = new ConcurrentHashMap<>();
    protected TaskStatus status = TaskStatus.PENDING;
    private final Lock statusLock = new ReentrantLock();
    protected FailureStrategy failureStrategy;
    protected ExecutionStrategy executionStrategy = ExecutionStrategy.AUTO;

    public AbstractTask(String taskId) {
        this.taskId = taskId;
    }

    @Override
    public String getTaskId() {
        return taskId;
    }

    @Override
    public void initialize() {
        status = TaskStatus.PENDING;
    }

    @Override
    public Map<String, Object> getParams() {
        return params;
    }

    @Override
    public void setParams(Map<String, Object> params) {
        this.params.putAll(params);
    }

    @Override
    public void run(ChainContext context, TaskScheduler scheduler) throws TaskExecutionException {
        setStatus(TaskStatus.RUNNING);
        try {
            execute(context,scheduler);
            setStatus(TaskStatus.SUCCESS);
        } catch (InterruptedException e) {
            setStatus(TaskStatus.INTERRUPTED);
            Thread.currentThread().interrupt();
            throw new TaskExecutionException("Task interrupted", e);
        } catch (Exception e) {
            setStatus(TaskStatus.FAILED);
            throw new TaskExecutionException("Task execution failed: " + e.getMessage(), e);
        }
    }

    @Override
    public TaskStatus getStatus() {
        return status;
    }

    @Override
    public void setStatus(TaskStatus status) {
        statusLock.lock();
        try {
            this.status = status;
        } finally {
            statusLock.unlock();
        }
    }

    @Override
    public void setFailureStrategy(FailureStrategy failureStrategy) {
        this.failureStrategy = failureStrategy;
    }

    @Override
    public FailureStrategy getFailureStrategy() {
        return failureStrategy;
    }

    @Override
    public void setExecutionStrategy(ExecutionStrategy executionStrategy) {
        this.executionStrategy = executionStrategy;
    }

    @Override
    public boolean isAsyncSupported() {
        return false;
    }
}
